import 'dart:math';
import 'dart:typed_data';

import 'package:animations/animations.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:fluentui_system_icons/fluentui_system_icons.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_displaymode/flutter_displaymode.dart';
import 'package:flutter_icons/flutter_icons.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:karyo/karyo.dart';
import 'dart:io' show File, Platform;
import 'package:package_info/package_info.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:http/http.dart' as http;
import 'package:dio/dio.dart';
import 'package:flutter_emoji/flutter_emoji.dart';



String getFontNameBySys() {
  if (isOnMobile()) {
    return FONT_NAME;
  } else {
    return FALL_BACK_FONT_NAME_EMOJI;
  }
}

buildAppBarTitle(
  String title,
  color,
  BuildContext context,
) {
  return Align(
    alignment: Alignment.centerLeft,
    child: Text(
      title,
      style: NORMAL_BOLD_TXT_STYLE.copyWith(color: color),
    ),
  );
}

buildBackButton(BuildContext context, Color color, {Function onPressed}) {
  return Row(
    crossAxisAlignment: CrossAxisAlignment.center,
    mainAxisAlignment: MainAxisAlignment.end,
    children: [
      // IconButton(
      //   padding: EdgeInsets.all(0),
      //   icon: Icon(FlutterIcons.ios_arrow_back_ion, color: color, size: 30,),
      //   onPressed: () => Navigator.of(context).pop(),
      // )
      IconButton(
        padding: EdgeInsets.all(0),
        icon: Icon(
          FluentIcons.chevron_left_24_filled,
          color: color,
          size: 28,
        ),
        onPressed:
            onPressed != null ? onPressed : () => Navigator.of(context).pop(),
      ),
    ],
  );
}

buildBackButtonCross(BuildContext context, color) {
  return IconButton(
    icon: Icon(
      FluentIcons.closed_caption_20_filled,
      color: Colors.grey,
      size: 25,
    ),
    onPressed: () => Navigator.of(context).pop(),
  );
}

showToast(BuildContext context, String msg, Color c,
    {Widget icon = const Icon(
      Icons.check,
      color: Colors.white,
    )}) {
  Fluttertoast.showToast(
    msg: msg,
    toastLength: Toast.LENGTH_SHORT,
    backgroundColor: c,
    textColor: Colors.white,
    timeInSecForIosWeb: 5,
  );
}

void showToastNoContext(String msg, Color c,
    {Widget icon = const Icon(
      Icons.check,
      color: Colors.white,
    )}) {
  Fluttertoast.showToast(
    msg: msg,
    toastLength: Toast.LENGTH_SHORT,
    backgroundColor: c,
    textColor: Colors.white,
    timeInSecForIosWeb: 5,
  );
}

showSnackbar(GlobalKey<ScaffoldState> scaffoldState, String message,
    {MaterialColor materialColor}) {
  if (message.isEmpty) return;
  // Find the Scaffold in the Widget tree and use it to show a SnackBar
  scaffoldState.currentState.showSnackBar(
      SnackBar(content: Text(message), backgroundColor: materialColor));
}

// Move to app widgets
Widget buildListTile(Widget leading, Widget title, Widget subtitle,
    Widget tailing, bool roundTop, bool roundBottom, onTap,
    {onTapDown,
    padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 6)}) {
  BorderRadius radius = BorderRadius.zero;
  double _radius = 15;
  if (roundTop) {
    radius = BorderRadius.only(
        topLeft: Radius.circular(_radius), topRight: Radius.circular(_radius));
  }
  if (roundBottom) {
    radius = BorderRadius.only(
        bottomLeft: Radius.circular(_radius),
        bottomRight: Radius.circular(_radius));
  }

  if (roundBottom && roundTop) {
    radius = BorderRadius.only(
        topLeft: Radius.circular(_radius),
        topRight: Radius.circular(_radius),
        bottomLeft: Radius.circular(_radius),
        bottomRight: Radius.circular(_radius));
  }
  return Card(
    elevation: 9,
    shadowColor: Colors.grey.withAlpha(20),
    margin: EdgeInsets.all(0),
    shape: RoundedRectangleBorder(
      borderRadius: radius,
    ),
    child: InkWell(
        borderRadius: radius,
        onTap: onTap,
        onTapDown: onTapDown,
        child: Padding(
          padding: padding,
          child: Row(
              mainAxisSize: MainAxisSize.min,
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                SizedBox(
                  width: 12,
                ),
                leading,
                SizedBox(
                  width: 18,
                ),
                Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[title, SizedBox(height: 2), subtitle],
                ),
                Expanded(
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: <Widget>[tailing, SizedBox(width: 8)],
                  ),
                )
              ]),
        )),
  );
}

Widget buildLDoubleListTile(
    Widget left, Widget right, bool roundTop, bool roundBottom, onTap1, onTap2,
    {onTapDown1, onTapDown2}) {
  BorderRadius radius = BorderRadius.zero;
  double _radius = 15;
  if (roundTop) {
    radius = BorderRadius.only(
        topLeft: Radius.circular(_radius), topRight: Radius.circular(_radius));
  }
  if (roundBottom) {
    radius = BorderRadius.only(
        bottomLeft: Radius.circular(_radius),
        bottomRight: Radius.circular(_radius));
  }

  if (roundBottom && roundTop) {
    radius = BorderRadius.only(
        topLeft: Radius.circular(_radius),
        topRight: Radius.circular(_radius),
        bottomLeft: Radius.circular(_radius),
        bottomRight: Radius.circular(_radius));
  }
  return Card(
    elevation: 9,
    shadowColor: Colors.grey.withAlpha(20),
    margin: EdgeInsets.all(0),
    shape: RoundedRectangleBorder(
      borderRadius: radius,
    ),
    child: Padding(
      padding: EdgeInsets.symmetric(horizontal: 6, vertical: 6),
      child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [
        Expanded(
          child: InkWell(
            borderRadius: radius,
            onTap: onTap1,
            onTapDown: onTapDown1,
            child: left,
          ),
        ),
        Expanded(
          child: InkWell(
            borderRadius: radius,
            onTap: onTap2,
            onTapDown: onTapDown2,
            child: right,
          ),
        )
      ]),
    ),
  );
}

Widget buildListTileNoShadow(BuildContext context, Widget leading, Widget title,
    Widget subtitle, Widget tailing, bool roundTop, bool roundBottom, onTap,
    {onTapDown}) {
  BorderRadius radius = BorderRadius.zero;
  double _radius = 5;
  if (roundTop) {
    radius = BorderRadius.only(
        topLeft: Radius.circular(_radius), topRight: Radius.circular(_radius));
  }
  if (roundBottom) {
    radius = BorderRadius.only(
        bottomLeft: Radius.circular(_radius),
        bottomRight: Radius.circular(_radius));
  }

  if (roundBottom && roundTop) {
    radius = BorderRadius.only(
        topLeft: Radius.circular(_radius),
        topRight: Radius.circular(_radius),
        bottomLeft: Radius.circular(_radius),
        bottomRight: Radius.circular(_radius));
  }
  return Card(
      elevation: 0,
      // shadowColor: Colors.grey.withAlpha(30),
      margin: EdgeInsets.all(0),
      color: Theme.of(context).scaffoldBackgroundColor,
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
      child: Padding(
        padding: EdgeInsets.symmetric(horizontal: 16, vertical: 6),
        child: InkWell(
            borderRadius: radius,
            onTap: onTap,
            onTapDown: onTapDown,
            child: Padding(
              padding: EdgeInsets.symmetric(horizontal: 6, vertical: 6),
              child: Row(mainAxisAlignment: MainAxisAlignment.start, children: [
                SizedBox(
                  width: 12,
                ),
                leading,
                SizedBox(
                  width: 18,
                ),
                Expanded(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      title,
                      SizedBox(height: 2),
                      Wrap(
                        children: [subtitle],
                      )
                    ],
                  ),
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.end,
                  children: <Widget>[tailing, SizedBox(width: 8)],
                ),
              ]),
            )),
      ));
}

Widget buildRoundedListTile(BuildContext context, Widget leading, Widget title,
    Widget subtitle, Widget tailing, bool roundTop, bool roundBottom, onTap,
    {onTapDown}) {
  BorderRadius radius = BorderRadius.zero;
  double _radius = 16;
  if (roundTop) {
    radius = BorderRadius.only(
        topLeft: Radius.circular(_radius), topRight: Radius.circular(_radius));
  }
  if (roundBottom) {
    radius = BorderRadius.only(
        bottomLeft: Radius.circular(_radius),
        bottomRight: Radius.circular(_radius));
  }

  if (roundBottom && roundTop) {
    radius = BorderRadius.only(
        topLeft: Radius.circular(_radius),
        topRight: Radius.circular(_radius),
        bottomLeft: Radius.circular(_radius),
        bottomRight: Radius.circular(_radius));
  }
  return Padding(
    padding: EdgeInsets.symmetric(horizontal: 16),
    child: Card(
      elevation: 10,
      margin: EdgeInsets.all(0),
      shape: RoundedRectangleBorder(borderRadius: radius),
      // color: Colors.grey.withAlpha(10),
      color: Theme.of(context).dialogBackgroundColor,
      shadowColor: Colors.grey.withAlpha(20),
      child: InkWell(
          borderRadius: radius,
          onTap: onTap,
          onTapDown: onTapDown,
          child: Padding(
            padding: EdgeInsets.symmetric(horizontal: 8, vertical: 12),
            child: Row(mainAxisAlignment: MainAxisAlignment.start, children: [
              SizedBox(
                width: 12,
              ),
              leading,
              SizedBox(
                width: 18,
              ),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    title,
                    SizedBox(height: 2),
                    Wrap(
                      children: [subtitle],
                    )
                  ],
                ),
              ),
              // Row(
              //   mainAxisAlignment: MainAxisAlignment.end,
              //   children: <Widget>[, SizedBox(width: 8)],
              // ),
              SizedBox(
                height: 32,
                child: tailing,
              ),
              SizedBox(width: 8),
            ]),
          )),
    ),
  );
}

Widget buildDivider() {
  return Padding(
    padding: EdgeInsets.symmetric(horizontal: 16),
    child: Container(
      color: Colors.grey.withAlpha(20),
      child: Divider(height: 0.2, color: Colors.grey.withAlpha(25), indent: 32),
    ),
  );
}

bool isAppInDarkMode(BuildContext context) {
  Brightness brightness = MediaQuery.platformBrightnessOf(context);
  return brightness == Brightness.dark;
}

void launchURL(String url) async {
  if (url.isEmpty) return;
  if (await canLaunch(url)) {
    await launch(url);
  } else {
    throw 'Could not launch $url';
  }
}

bool isOnMobile() {
  return Platform.isIOS || Platform.isAndroid;
}

bool isOniPhone() {
  return Platform.isIOS;
}

bool isOnLinux() {
  return Platform.isLinux;
}

bool isDarkModeOn(BuildContext context) {
  var brightness = MediaQuery.of(context).platformBrightness;
  bool darkModeOn = brightness == Brightness.dark;
  return darkModeOn;
}

bool isDarkModeOnNoContext() {
  return SchedulerBinding.instance.window.platformBrightness == Brightness.dark;
}

Future<DisplayMode> getCurrentMode() async {
  return await FlutterDisplayMode.current;
}

void initDefaultRefreshRate() async {
  final DisplayMode m = await getCurrentMode();
  await FlutterDisplayMode.setMode(m);
  print('已经设置为默认刷新率: $m');
}

Future<String> getAppName() async {
  PackageInfo packageInfo = await PackageInfo.fromPlatform();
  return packageInfo.appName;
}

Future<String> getAppVersion() async {
  PackageInfo packageInfo = await PackageInfo.fromPlatform();
  return packageInfo.version;
}

Future<String> getBuildNumber() async {
  PackageInfo packageInfo = await PackageInfo.fromPlatform();
  return packageInfo.buildNumber;
}

Future<String> getDeviceIdentifier() async {
  String deviceIdentifier = "unknown";
  DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();

  if (Platform.isAndroid) {
    AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
    deviceIdentifier = androidInfo.androidId;
  } else if (Platform.isIOS) {
    IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
    deviceIdentifier = iosInfo.identifierForVendor;
  } else if (kIsWeb) {
    // The web doesnt have a device UID, so use a combination fingerprint as an example
    WebBrowserInfo webInfo = await deviceInfo.webBrowserInfo;
    deviceIdentifier = webInfo.vendor +
        webInfo.userAgent +
        webInfo.hardwareConcurrency.toString();
  } else if (Platform.isLinux) {
    LinuxDeviceInfo linuxInfo = await deviceInfo.linuxInfo;
    deviceIdentifier = linuxInfo.machineId;
  } else if (Platform.isWindows) {
    WindowsDeviceInfo windowsDeviceInfo = await deviceInfo.windowsInfo;
    deviceIdentifier = windowsDeviceInfo.computerName;
  } else if (Platform.isMacOS) {
    MacOsDeviceInfo macosDeviceInfo = await deviceInfo.macOsInfo;
    deviceIdentifier = macosDeviceInfo.computerName + macosDeviceInfo.model;
  }
  return deviceIdentifier;
}

Future<String> getDeviceName() async {
  String deviceIdentifier = "unknown";
  DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();

  if (Platform.isAndroid) {
    AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
    deviceIdentifier = androidInfo.manufacturer + androidInfo.model;
  } else if (Platform.isIOS) {
    IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
    deviceIdentifier = iosInfo.name + iosInfo.model;
  } else if (kIsWeb) {
    // The web doesnt have a device UID, so use a combination fingerprint as an example
    WebBrowserInfo webInfo = await deviceInfo.webBrowserInfo;
    deviceIdentifier = webInfo.vendor +
        webInfo.userAgent +
        webInfo.hardwareConcurrency.toString();
  } else if (Platform.isLinux) {
    LinuxDeviceInfo linuxInfo = await deviceInfo.linuxInfo;
    deviceIdentifier = linuxInfo.prettyName;
  } else if (Platform.isWindows) {
    WindowsDeviceInfo windowsDeviceInfo = await deviceInfo.windowsInfo;
    deviceIdentifier = windowsDeviceInfo.computerName;
  } else if (Platform.isMacOS) {
    MacOsDeviceInfo macosDeviceInfo = await deviceInfo.macOsInfo;
    deviceIdentifier = macosDeviceInfo.computerName + macosDeviceInfo.model;
  }
  return deviceIdentifier;
}

Future<bool> saveNetworkImageToLocal(String imageUrl) async {
  var response = await Dio()
      .get(imageUrl, options: Options(responseType: ResponseType.bytes));
  File file = new File(imageUrl);
  String fileName = file.path.split('/').last;
  final result = await ImageGallerySaver.saveImage(
      Uint8List.fromList(response.data),
      quality: 100,
      name: fileName);
  if (result['filePath'] == null) {
    return false;
  }
  return true;
}

class PageRoutes {
  static const double kDefaultDuration = .45;
  static const Curve kDefaultEaseFwd = Curves.fastOutSlowIn;
  static const Curve kDefaultEaseReverse = Curves.easeOut;

  static Route<T> sharedAxis<T>(Widget page,
      [SharedAxisTransitionType type = SharedAxisTransitionType.scaled,
      double duration = kDefaultDuration]) {
    return PageRouteBuilder<T>(
      transitionDuration: Duration(milliseconds: (duration * 1000).round()),
      pageBuilder: (context, animation, secondaryAnimation) => page,
      transitionsBuilder: (context, animation, secondaryAnimation, child) {
        return SharedAxisTransition(
          child: child,
          animation: animation,
          secondaryAnimation: secondaryAnimation,
          transitionType: type,
        );
      },
    );
  }
}
